package com.jade.explorer.views;

import java.io.File;
import java.util.ArrayList;

import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.*;
import org.eclipse.core.commands.Command;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IParameter;
import org.eclipse.core.commands.NotEnabledException;
import org.eclipse.core.commands.NotHandledException;
import org.eclipse.core.commands.Parameterization;
import org.eclipse.core.commands.ParameterizedCommand;
import org.eclipse.core.commands.common.NotDefinedException;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.jface.viewers.*;
import org.eclipse.jface.action.*;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.ui.*;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.SWT;
import com.jade.explorer.dirscan.*;
import com.jade.explorer.ui.CloneDialog;
import com.jade.explorer.ui.NewFileDialog;
import com.jade.explorer.ui.NewProjectDialog;
import com.jade.explorer.ui.exp.MultiExportDialog;
import com.jade.explorer.ui.exp.MultiFileExportDialog;
import com.jade.explorer.ui.exp.SingleFileExportDialog;
import com.jade.explorer.ui.imp.IImportDialog;
import com.jade.explorer.ui.imp.MultiImportDialog;
import com.jade.explorer.ui.imp.ProjectImportDialog;
import com.jade.explorer.ui.imp.SingleImportDialog;
import com.jade.explorer.ui.property.ImageProperty;
import com.jade.explorer.ui.property.ProjectProperty;
import com.jade.logger.Logger;

import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.handlers.IHandlerService;

public class Explorer extends ViewPart {
	
	//------------------------------Public static
	public static final String ID = "com.jade.explorer.views.Explorer";
	
	
	//------------------------------Private fields
	private TreeViewer viewer;
	private DrillDownAdapter drillDownAdapter;
	private Action doubleClickAction;
	private WorkspaceScanner workspaceScanner;
	private TreeParent invisibleRoot;											
	
	private Action actionDelete;
	private Action actionNewObject;
	private Action actionNewAnisotropy;
	private Action actionNewDomain;
	private Action actionImport;
	private Action actionExport;
	private Action actionViewSource;
	private Action actionClone;
	private Action actionOpenObject;
	private Action actionOpenAnisotropy;
	private Action actionOpenDomain;
	private Action actionNewProject;
	private Action actionProjectProperties;
	private Action actionObjectProperties;
	private Action actionDomainProperties;
	private Action actionAnisotropyProperties;
	private Action actionImageProperties;
	private Action actionRefresh;
	private Action actionImportProject;
	 
	
	//------------------------------Private methods
	public void createPartControl(Composite parent) {
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		workspaceScanner = new WorkspaceScanner(workspace.getRoot().getLocation().toString());
		
		viewer = new TreeViewer(parent, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL);
		drillDownAdapter = new DrillDownAdapter(viewer);
		viewer.setContentProvider(new ViewContentProvider());
		viewer.setLabelProvider(new ViewLabelProvider());
		viewer.setSorter(new NameSorter());
		viewer.setInput(getViewSite());

		PlatformUI.getWorkbench().getHelpSystem().setHelp(viewer.getControl(), "com.jade.explorer.viewer");
		
		makeActions();
		
		hookContextMenu();
		hookDoubleClickAction();
		contributeToActionBars();
		
	}
	
	
	private String pathToProjectCorrect(String path, String folder){
		
		if(path.toLowerCase().indexOf(folder.toLowerCase()) < 0){
			path += "\\" + folder;
		}
		
		return path;
	}
	
	
	private void hookContextMenu() {
		MenuManager menuMgr = new MenuManager("#PopupMenu");
		menuMgr.setRemoveAllWhenShown(true);
		menuMgr.addMenuListener(new IMenuListener() {
			public void menuAboutToShow(IMenuManager manager) {
				Explorer.this.fillContextMenu(manager);
			}
		});
		Menu menu = menuMgr.createContextMenu(viewer.getControl());
		viewer.getControl().setMenu(menu);
		getSite().registerContextMenu(menuMgr, viewer);
	}
	
	
	private void fillContextMenu(IMenuManager manager) {
		
		MenuManager newFilesMng = new MenuManager("New...");
		newFilesMng.setRemoveAllWhenShown(true);
		newFilesMng.addMenuListener(new IMenuListener(){
			public void menuAboutToShow(IMenuManager newFilesMenu){
				Explorer.this.fillNewFilesMenu(newFilesMenu);
			}
		});
		
		MenuManager openObjectWithMng = new MenuManager("Open With...");
		openObjectWithMng.setRemoveAllWhenShown(true);
		openObjectWithMng.addMenuListener(new IMenuListener(){
			public void menuAboutToShow(IMenuManager openObjectWith){
				Explorer.this.fillOpenObjectWithMenu(openObjectWith);
			}
		});
		
		MenuManager openAnisotropyWithMng = new MenuManager("Open With...");
		openAnisotropyWithMng.setRemoveAllWhenShown(true);
		openAnisotropyWithMng.addMenuListener(new IMenuListener(){
			public void menuAboutToShow(IMenuManager openObjectWith){
				Explorer.this.fillOpenAnisotropyWithMenu(openObjectWith);
			}
		});
		
		MenuManager openDomainWithMng = new MenuManager("Open With...");
		openDomainWithMng.setRemoveAllWhenShown(true);
		openDomainWithMng.addMenuListener(new IMenuListener(){
			public void menuAboutToShow(IMenuManager openObjectWith){
				Explorer.this.fillOpenDomainWithMenu(openObjectWith);
			}
		});
		
		
		if (viewer.getSelection() instanceof IStructuredSelection) {
			
			IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
            TreeObject tp = (TreeObject)selection.getFirstElement();
            
            if (tp instanceof TreeObject){
            	
            	switch(tp.getType()){
            		case IMAGE : {
            			manager.add(actionExport);
            			manager.add(actionDelete);
            			manager.add(actionImageProperties);
            		} break;
            		
            		case ANISOTROPY : {
            			manager.add(actionOpenAnisotropy);
            			manager.add(openAnisotropyWithMng);
            			manager.add(actionViewSource);
            			manager.add(actionClone);
            			manager.add(actionExport);
            			manager.add(actionDelete);
            			manager.add(actionAnisotropyProperties);
            		} break;
            		
            		case OBJECT : {
            			manager.add(actionOpenObject);
            			manager.add(openObjectWithMng);
            			manager.add(actionViewSource);
            			manager.add(actionClone);
            			manager.add(actionExport);
            			manager.add(actionDelete);
            			manager.add(actionObjectProperties);
            		} break;
            		
            		case FOLDER : {
            			if(tp.getPath().toLowerCase().indexOf("object") >= 0){
            				manager.add(actionNewObject);
            				manager.add(actionImport);
            				manager.add(actionExport);
            			}
            			else if(tp.getPath().toLowerCase().indexOf("anisotropy") >= 0){
            				manager.add(actionNewAnisotropy);
            				manager.add(actionImport);
            				manager.add(actionExport);
            			}
            			else if(tp.getPath().toLowerCase().indexOf("placement") >= 0){
            				manager.add(actionNewDomain);
            				manager.add(actionImport);
            				manager.add(actionExport);
            			}
            			else{
            				manager.add(actionDelete);
            			}
            		} break;
            		
            		case PROJECT : {
            			manager.add(newFilesMng);
            			manager.add(actionImport);
        				manager.add(actionExport);
            			manager.add(actionDelete);
            			manager.add(actionProjectProperties);
            			
            		} break;
            		
            		case DOMAIN : {
            			manager.add(actionOpenDomain);
            			manager.add(openDomainWithMng);
            			manager.add(actionViewSource);
            			manager.add(actionClone);
            			manager.add(actionExport);
            			manager.add(actionDelete);
            			manager.add(actionDomainProperties);
            		} break;
            		
            		case UNKNOWN : {
            			manager.add(actionDelete);
            		} break;
            		
            		default : break;
            	}
            }
        }
		
		// Other plug-ins can contribute there actions here
		manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
		
		
	}
	
	
	private void fillOpenObjectWithMenu(IMenuManager openObjectWith) {
		//TODO open object with contributor extension
		openObjectWith.add(actionOpenObject); //Delete
		openObjectWith.add(new Separator());
	}
	
	private void fillOpenAnisotropyWithMenu(IMenuManager openObjectWith) {
		//TODO open object with contributor extension
		openObjectWith.add(actionOpenAnisotropy); //Delete
		openObjectWith.add(new Separator());
	}
	
	private void fillOpenDomainWithMenu(IMenuManager openObjectWith) {
		//TODO open object with contributor extension
		openObjectWith.add(actionOpenDomain); //Delete
		openObjectWith.add(new Separator());
	}

	//------------------------------Constructors
	public Explorer() {
	}

	/**
	 * This is a callback that will allow us
	 * to create the viewer and initialize it.
	 */
	

	

	private void contributeToActionBars() {
		IActionBars bars = getViewSite().getActionBars();
		fillLocalToolBar(bars.getToolBarManager());
	}

	
	private void fillLocalToolBar(IToolBarManager manager) {
		manager.add(actionNewProject);
		manager.add(actionImportProject);
		manager.add(actionRefresh);
		manager.add(new Separator());
		drillDownAdapter.addNavigationActions(manager);
	}
	
	
	private void fillNewFilesMenu(IMenuManager newFiles){
		
		newFiles.add(actionNewObject);
		newFiles.add(actionNewAnisotropy);
		newFiles.add(actionNewDomain);
		
	}

	
	private void makeActions() {
		
		actionDelete = new Action(){
			public void run(){
				IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
				
				if(selection.toArray().length > 1){
					if(confirmDialog("Delete", "Delete these files?")){
						for(int i = 0; i < selection.toArray().length; i++){
							TreeObject to =  (TreeObject)selection.toArray()[i];
							invisibleRoot.removeChildByPath(to.getPath());
							Logger.print(Logger.STATE_SUCCESS, "File removed: \"" + to.getPath() + "\"");
							viewer.refresh();
						}
					}
				}else{
					
					
					if (selection.getFirstElement() instanceof Project){
						TreeObject tp = (Project)selection.getFirstElement();
						if(confirmDialog("Delete", "Delete " + tp.getName() + "?")){
							invisibleRoot.removeChildByPath(tp.getPath());
							if (FileSystem.removeFolder(tp.getPath()))
								Logger.print(Logger.STATE_SUCCESS, "Project removed: \"" + tp.getPath() + "\"");
							else
								Logger.print(Logger.STATE_ERROR, "Project remove error: \"" + tp.getPath() + "\"");
							viewer.refresh();
						}
					}
					
					else if (selection.getFirstElement() instanceof TreeObject){
						TreeObject tp = (TreeObject)selection.getFirstElement();
						if(confirmDialog("Delete", "Delete " + tp.getName() + "?")){
							invisibleRoot.removeChildByPath(tp.getPath());	     
							Logger.print(Logger.STATE_SUCCESS, "File removed: \"" + tp.getPath() + "\"");
							viewer.refresh();
						}
					}
					
				}
				
				
				
				
				
			}
		};
		actionDelete.setText("Delete");
		actionDelete.setToolTipText("Delete this file from system");
		actionDelete.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_ETOOL_DELETE));
		
		actionNewObject = new Action(){
			public void run(){
				IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
	            TreeObject tp = (TreeObject)selection.getFirstElement();
	            
	            NewFileDialog a = new NewFileDialog(viewer.getControl().getShell(),
						"New Object",
						"Enter Object name:",
						".jade");
				a.open();
	            String result = a.getResult(); 
	            if (!result.equals("") && result != null){
	            	String location = pathToProjectCorrect(tp.getPath().toString(), "Objects");
	            	FileSystem.createNewObject(location + "\\" + result);
	            	invisibleRoot.addChildbyPath(location + "\\" + result);
	            	Logger.print(Logger.STATE_SUCCESS, "New Object \"" + result + "\" was created ");
	            	viewer.refresh();
	            	
	            }
			}
		};
		actionNewObject.setText("New Object");
		actionNewObject.setToolTipText("Creates new object in current folder");
		actionNewObject.setImageDescriptor(JadeSharedImages.getImageDescriptor(JadeSharedImages.IMG_LAYER_SHAPE_PLUS));
		
		actionNewAnisotropy = new Action(){
			public void run(){
				IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
	            TreeObject tp = (TreeObject)selection.getFirstElement();
	            
	            NewFileDialog a = new NewFileDialog(viewer.getControl().getShell(),
						"New Anisotropy",
						"Enter Anisotropy name:",
						".ani");
				a.open();
	            String result = a.getResult(); 
	            if (!result.equals("") && result != null){
	            	String location = pathToProjectCorrect(tp.getPath().toString(), "Anisotropy");
	            	FileSystem.createNewObject(location + "\\" + result);
	            	invisibleRoot.addChildbyPath(location + "\\" + result);
	            	Logger.print(Logger.STATE_SUCCESS, "New Anisotropy \"" + result + "\" was created ");
	            	viewer.refresh();
	            }
			}
		};
		actionNewAnisotropy.setText("New Anisotropy");
		actionNewAnisotropy.setToolTipText("Creates new anisotropy in current folder");
		actionNewAnisotropy.setImageDescriptor(JadeSharedImages.getImageDescriptor(JadeSharedImages.IMG_ANISOTROPY_RED_PLUS));
		
		actionNewDomain = new Action(){
			public void run(){
				IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
	            TreeObject tp = (TreeObject)selection.getFirstElement();
	            
	            NewFileDialog a = new NewFileDialog(viewer.getControl().getShell(),
						"New Domain",
						"Enter Domain name:",
						".domain");
				a.open();
	            String result = a.getResult(); 
	            if (!result.equals("") && result != null){
	            	String location = pathToProjectCorrect(tp.getPath().toString(), "Placement");
	            	FileSystem.createNewObject(location + "\\" + result);
	            	invisibleRoot.addChildbyPath(location + "\\" + result);
	            	Logger.print(Logger.STATE_SUCCESS, "New Domain \"" + result + "\" was created ");
	            	viewer.refresh();
	            	
	            }
			}
		};
		actionNewDomain.setText("New Domain");
		actionNewDomain.setToolTipText("Creates new domain in current folder");
		actionNewDomain.setImageDescriptor(JadeSharedImages.getImageDescriptor(JadeSharedImages.IMG_DOMAIN_GORIZOTAL_PLUS));
		
		actionImport = new Action(){
			public void run(){
				IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
				IImportDialog diag = null;
				
				if (selection.getFirstElement() instanceof Project){
					Project p = (Project) selection.getFirstElement();
					diag = new MultiImportDialog(viewer.getControl().getShell(), p.getPath());
				}
				else if (selection.getFirstElement() instanceof TreeParent){
					TreeParent t = (TreeParent) selection.getFirstElement();
					diag = new SingleImportDialog(viewer.getControl().getShell(), t.getPath());
				}

				
				diag.openDialog();
				
				if (diag.getCode() == 0 && diag.getResult()){
					
					refresh();
					
					Logger.print(Logger.STATE_SUCCESS, "Files imported successfully");
				}
				
				
				viewer.refresh();
			}
		};
		actionImport.setText("Import...");
		actionImport.setToolTipText("Import selected object to current project");
		actionImport.setImageDescriptor(JadeSharedImages.getImageDescriptor(JadeSharedImages.IMG_IMPORT));
		
		actionImportProject = new Action(){
			public void run(){
				IWorkspace workspace = ResourcesPlugin.getWorkspace();
				IImportDialog i = new ProjectImportDialog(viewer.getControl().getShell(), workspace.getRoot().getLocation().toString());
				i.openDialog();
				
				if (i.getCode() == 0 && i.getResult()){
					refresh();
					Logger.print(Logger.STATE_SUCCESS, "Project was successfuly imported.");
				}
			}
		};
		actionImportProject.setText("Import...");
		actionImportProject.setToolTipText("Import project to workspace");
		actionImportProject.setImageDescriptor(JadeSharedImages.getImageDescriptor(JadeSharedImages.IMG_IMPORT));
		
		actionExport = new Action(){
			public void run(){
				IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();

				if(selection.getFirstElement() instanceof Project){
					Project p = (Project) selection.getFirstElement();
					MultiExportDialog med = new MultiExportDialog(viewer.getControl().getShell(), p.getPath());
					med.open();
					
					if (med.getResult() && med.getReturnCode() == 0){
						Logger.print(Logger.STATE_SUCCESS, "Files successfully exported.");
					}
					else if (!med.getResult() && med.getReturnCode() == 0){
						Logger.print(Logger.STATE_ERROR, "File export error.");
					}
				}
				else if (selection.getFirstElement() instanceof TreeParent){
					TreeObject tp = (TreeParent) selection.getFirstElement();
					
					MultiFileExportDialog d = new MultiFileExportDialog(viewer.getControl().getShell(), tp.getPath());
					d.open();
					
					if (d.getResult() && d.getReturnCode() == 0)
						Logger.print(Logger.STATE_SUCCESS, "Files successfully exported.");
					else if (!d.getResult() && d.getReturnCode() == 0)
						Logger.print(Logger.STATE_ERROR, "File export error.");
					
					
				}
				else if (selection.getFirstElement() instanceof TreeObject){
					TreeObject to = (TreeObject) selection.getFirstElement();
					
					SingleFileExportDialog d = new SingleFileExportDialog(viewer.getControl().getShell(), to.getPath());
					d.open();
					
					if (d.getResult() && d.getReturnCode() == 0)
						Logger.print(Logger.STATE_SUCCESS, "File \"" + to.getPath() + "\" exported.");
					else if (!d.getResult() && d.getReturnCode() == 0)
						Logger.print(Logger.STATE_ERROR, "File export error.");
					
				}
				
				
				
				
			}
		};
		actionExport.setText("Export...");
		actionExport.setToolTipText("Export selected objects");
		actionExport.setImageDescriptor(JadeSharedImages.getImageDescriptor(JadeSharedImages.IMG_EXPORT));
		
		actionViewSource = new Action(){
			public void run(){		
				
				ArrayList<Parameterization> parameters = new ArrayList<Parameterization>();
				IParameter iparam = null;
				 
				IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
				ICommandService cmdService = (ICommandService)window.getService(ICommandService.class);
				Command cmd = cmdService.getCommand("com.jade.sourceviewer.commands.viewSource");
				 
				try {
					iparam = cmd.getParameter("com.jade.sourceviewer.commandParamPath");
				} catch (NotDefinedException e) {
					e.printStackTrace();
				}
				
				IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
	            TreeObject tp = (TreeObject)selection.getFirstElement();
				
				Parameterization params = new Parameterization(iparam, tp.getPath());
				parameters.add(params);
				 
				ParameterizedCommand pc = new ParameterizedCommand(cmd, (Parameterization[]) parameters.toArray(new Parameterization[parameters.size()]));
				 
				IHandlerService handlerService = (IHandlerService)window.getService(IHandlerService.class);
				try {
					handlerService.executeCommand(pc, null);
				} catch (ExecutionException | NotDefinedException | NotEnabledException | NotHandledException e) {
					e.printStackTrace();
				}
				
			
			}
		};
		actionViewSource.setText("View Source");
		actionViewSource.setToolTipText("View Source");
		actionViewSource.setImageDescriptor(JadeSharedImages.getImageDescriptor(JadeSharedImages.IMG_VIEW_SOURCE));
		
		actionClone = new Action(){
			public void run(){
				
				IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
				TreeObject to = (TreeObject)selection.getFirstElement();
				
				CloneDialog cd = new CloneDialog(viewer.getControl().getShell(), to.getPath(), to.getExtension());
				cd.open();
				
				String result = cd.getClone(); 
	            if (!result.equals("") && result != null){
	            	
	            	invisibleRoot.addChildbyPath(result);
	            	Logger.print(Logger.STATE_SUCCESS, "File cloned: \"" + result + "\" was created ");
	            	viewer.refresh();
	            	
	            }
				
				viewer.refresh();
			}
		};
		actionClone.setText("Clone");
		actionClone.setToolTipText("Creates similar object to seleted one");
		actionClone.setImageDescriptor(JadeSharedImages.getImageDescriptor(JadeSharedImages.IMG_LAYERS));
		
		actionOpenObject = new Action(){
			public void run(){
				//showMessage("open object");
				//TODO open object action
				
				openObject();

			}
		};
		actionOpenObject.setText("Open");
		actionOpenObject.setToolTipText("Open Object");
		
		actionOpenAnisotropy = new Action(){
			public void run(){
				openAnisotropy();
				//showMessage("open anisotropy");
				//TODO open anisotropy action
			}
		};
		actionOpenAnisotropy.setText("Open");
		actionOpenAnisotropy.setToolTipText("Open Anisotropy");
		
		actionOpenDomain = new Action(){
			public void run(){
				openDomain();
//				showMessage("open domain");
				//TODO open domain action
			}
		};
		actionOpenDomain.setText("Open");
		actionOpenDomain.setToolTipText("Open Domain");
		
		actionNewProject = new Action(){
			public void run(){
				IWorkspace workspace = ResourcesPlugin.getWorkspace();
				File ws = new File(workspace.getRoot().getLocation().toString());
				NewProjectDialog pd = new NewProjectDialog(viewer.getControl().getShell(), ws.toString());
				pd.open();
				String result = pd.getName();
				String wpath = ws.toString() + "\\" + result;
				
				if (result != "" && result != null){
					
					Project p = new Project(result, wpath);
					TreeParent obj = new TreeParent("Objects", wpath + "\\Objects");
					TreeParent ani = new TreeParent("Anisotropy", wpath + "\\Anisotropy");
					TreeParent dom = new TreeParent("Placement", wpath + "\\Placement");
					p.addChild(ani);
					p.addChild(obj);
					p.addChild(dom);
					
					invisibleRoot.addChild(p);
					viewer.refresh();
				}
			}
		};
		actionNewProject.setText("New Project");
		actionNewProject.setToolTipText("New Project");
		actionNewProject.setImageDescriptor(JadeSharedImages.getImageDescriptor(JadeSharedImages.IMG_FOLDER_PLUS));
		
		actionProjectProperties = new Action(){
			public void run(){
				IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
	            TreeObject tp = (TreeObject)selection.getFirstElement();
				ProjectProperty pp = new ProjectProperty(viewer.getControl().getShell(), tp.getPath());
				pp.open();
			}
		};
		actionProjectProperties.setText("Properties");
		actionProjectProperties.setToolTipText("Project Properties");
		actionProjectProperties.setImageDescriptor(JadeSharedImages.getImageDescriptor(JadeSharedImages.FUN_GAME_MONITOR));
		
		actionObjectProperties = new Action(){
			public void run(){
				//TODO object property window
			}
		};
		actionObjectProperties.setText("Properties");
		actionObjectProperties.setToolTipText("Object Properties");
		actionObjectProperties.setImageDescriptor(JadeSharedImages.getImageDescriptor(JadeSharedImages.FUN_GAME_MONITOR));
		
		actionDomainProperties = new Action(){
			public void run(){
				//TODO domain property window
			}
		};
		actionDomainProperties.setText("Properties");
		actionDomainProperties.setToolTipText("Domain Properties");
		actionDomainProperties.setImageDescriptor(JadeSharedImages.getImageDescriptor(JadeSharedImages.FUN_GAME_MONITOR));
		
		actionAnisotropyProperties = new Action(){
			public void run(){
				//TODO anisotropy property window
			}
		};
		actionAnisotropyProperties.setText("Properties");
		actionAnisotropyProperties.setToolTipText("Anisotropy Properties");
		actionAnisotropyProperties.setImageDescriptor(JadeSharedImages.getImageDescriptor(JadeSharedImages.FUN_GAME_MONITOR));
		
		actionImageProperties  = new Action(){
			public void run(){
				IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
	            TreeObject tp = (TreeObject)selection.getFirstElement();
				
				ImageProperty ip = new ImageProperty(viewer.getControl().getShell(), tp.getPath(), tp.getName(), tp.getExtension());
				ip.open();
			}
		};
		actionImageProperties.setText("Properties");
		actionImageProperties.setToolTipText("Image Properties");
		actionImageProperties.setImageDescriptor(JadeSharedImages.getImageDescriptor(JadeSharedImages.FUN_GAME_MONITOR));
		
		actionRefresh = new Action(){
			public void run(){
				refresh();
			}
		};
		actionRefresh.setText("Refresh");
		actionRefresh.setToolTipText("Refresh viewer");
		actionRefresh.setImageDescriptor(JadeSharedImages.getImageDescriptor(JadeSharedImages.IMG_REFRESH));
		
		//--------------------------------------------
		
		doubleClickAction = new Action() {
			public void run() {
				//TODO double click action
				IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
				TreeObject tp = (TreeObject) selection.getFirstElement();
				
				if(tp.getType() == FileType.OBJECT)
					openObject();
				
				if(tp.getType() == FileType.ANISOTROPY)
					openAnisotropy();
				if(tp.getType() == FileType.DOMAIN)
					openDomain();
			}
		};
		
		
	}

	private void hookDoubleClickAction() {
		viewer.addDoubleClickListener(new IDoubleClickListener() {
			public void doubleClick(DoubleClickEvent event) {
				doubleClickAction.run();
			}
		});
	}
	
	private void showMessage(String message) {
		MessageDialog.openInformation(
			viewer.getControl().getShell(),
			"Project explorer",
			message);
	}
	
	
	private boolean confirmDialog(String header, String text){
		return MessageDialog.openQuestion(viewer.getControl().getShell(), header, text);
	}

	
	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
		viewer.getControl().setFocus();
	}
	
	
	private void refresh(){
		invisibleRoot.punishAll();
		invisibleRoot = null;
		
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		workspaceScanner = new WorkspaceScanner(workspace.getRoot().getLocation().toString());
		
		invisibleRoot = new TreeParent("invisible root", workspaceScanner.getWorkspaceDir());

		for(int i = 0; i < workspaceScanner.count(); i++){
			invisibleRoot.addChild(workspaceScanner.ProjectList().get(i));
		}
		viewer.refresh();
		
	}
	
	private void openObject(){
		
		ArrayList<Parameterization> parameters = new ArrayList<Parameterization>();
		IParameter iparam = null;
		 
		IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
		ICommandService cmdService = (ICommandService)window.getService(ICommandService.class);
		Command cmd = cmdService.getCommand("com.jade.editor.object.command.openObject");
		 
		try {
			iparam = cmd.getParameter("com.jade.editor.object.paramPath");
		} catch (NotDefinedException e) {
			e.printStackTrace();
		}
		
		IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        TreeObject tp = (TreeObject)selection.getFirstElement();
		
		Parameterization params = new Parameterization(iparam, tp.getPath());
		parameters.add(params);
		 
		ParameterizedCommand pc = new ParameterizedCommand(cmd, (Parameterization[]) parameters.toArray(new Parameterization[parameters.size()]));
		 
		IHandlerService handlerService = (IHandlerService)window.getService(IHandlerService.class);
		try {
			handlerService.executeCommand(pc, null);
		} catch (ExecutionException | NotDefinedException | NotEnabledException | NotHandledException e) {
			e.printStackTrace();
		}
		
	}
	
	private void openAnisotropy(){
		
		ArrayList<Parameterization> parameters = new ArrayList<Parameterization>();
		IParameter iparam = null;
		 
		IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
		ICommandService cmdService = (ICommandService)window.getService(ICommandService.class);
		Command cmd = cmdService.getCommand("com.jade.editor.anisotropy.command.openAnisotropy");
		 
		try {
			iparam = cmd.getParameter("com.jade.editor.anisotropy.paramPath");
		} catch (NotDefinedException e) {
			e.printStackTrace();
		}
		
		IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        TreeObject tp = (TreeObject)selection.getFirstElement();
		
		Parameterization params = new Parameterization(iparam, tp.getPath());
		parameters.add(params);
		 
		ParameterizedCommand pc = new ParameterizedCommand(cmd, (Parameterization[]) parameters.toArray(new Parameterization[parameters.size()]));
		 
		IHandlerService handlerService = (IHandlerService)window.getService(IHandlerService.class);
		try {
			handlerService.executeCommand(pc, null);
		} catch (ExecutionException | NotDefinedException | NotEnabledException | NotHandledException e) {
			e.printStackTrace();
		}
		
	}
	
	private void openDomain(){
		
		ArrayList<Parameterization> parameters = new ArrayList<Parameterization>();
		IParameter iparam = null;
		 
		IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
		ICommandService cmdService = (ICommandService)window.getService(ICommandService.class);
		Command cmd = cmdService.getCommand("com.jade.editor.domain.command.openDomain");
		 
		try {
			iparam = cmd.getParameter("com.jade.editor.domain.paramPath");
		} catch (NotDefinedException e) {
			e.printStackTrace();
		}
		
		IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
        TreeObject tp = (TreeObject)selection.getFirstElement();
		
		Parameterization params = new Parameterization(iparam, tp.getPath());
		parameters.add(params);
		 
		ParameterizedCommand pc = new ParameterizedCommand(cmd, (Parameterization[]) parameters.toArray(new Parameterization[parameters.size()]));
		 
		IHandlerService handlerService = (IHandlerService)window.getService(IHandlerService.class);
		try {
			handlerService.executeCommand(pc, null);
		} catch (ExecutionException | NotDefinedException | NotEnabledException | NotHandledException e) {
			e.printStackTrace();
		}
		
	}
	
	//------------------------------Inner classes
	
	class ViewContentProvider implements IStructuredContentProvider, ITreeContentProvider {
	
		public void inputChanged(Viewer v, Object oldInput, Object newInput) {}
		
		public void dispose() {}
		
		public Object[] getElements(Object parent) {
			if (parent.equals(getViewSite())) {
				if (invisibleRoot==null) initialize();
				return getChildren(invisibleRoot);
			}
			return getChildren(parent);
		}
		
		public Object getParent(Object child) {
			if (child instanceof TreeObject) {
				return ((TreeObject)child).getParent();
			}
			return null;
		}
		
		public Object [] getChildren(Object parent) {
			if (parent instanceof TreeParent) {
				return ((TreeParent)parent).getChildren();
			}
			return new Object[0];
		}
		
		public boolean hasChildren(Object parent) {
			if (parent instanceof TreeParent)
				return ((TreeParent)parent).hasChildren();
			return false;
		}
		
		private void initialize() {
			
			invisibleRoot = new TreeParent("invisible root", workspaceScanner.getWorkspaceDir());

			for(int i = 0; i < workspaceScanner.count(); i++){
				invisibleRoot.addChild(workspaceScanner.ProjectList().get(i));
			}
		}
	}
	
	
	class NameSorter extends ViewerSorter {}
	
}
